#include "editor_spriteset.h"
#include "editor_main.h"
#include "editor_brush.h"

#include "ui/ui_manager.h"
#include "ui/sprite_set.h"
#include "application/game_script.h"

#include "script/file_list.h"
#include "script/scripthelper.h"

#include "util/mmgr.h"		    // Needs to come in early
#include "util/common_macros.h"		// macros
#include "util/log.h"		    // logging
#include "util/timer.h"		    // logging

#include <algorithm>
#include <cassert>

using namespace LuaPlus;
using namespace editor;
using namespace script;

UISpriteSet::UISpriteSet(EditorBrush*	pBrush, const std::string& Name) :
	UISelection(pBrush, Name)
{
	for (int i=0; i<WIDGET_C; i++)
		m_WidgetA[i]=0;

	m_pPanel = ui::UIManager::Instance().GetPanel("editor_panel");
	if (!m_pPanel)
		m_pPanel = ui::UIManager::Instance().AddPanel("ui/editor_panel.ui");

	if (m_pPanel)
	{
		ui::UIManager::Instance().PushPanelToFront(m_pPanel);

		if (ui::UIWidget* pWidget = m_pPanel->GetWidgetByName("ArrowUp"))
			pWidget->SetReleaseLMBEventDg(UI_DELEGATE(UISpriteSet, OnScrollUp));
		if (ui::UIWidget* pWidget = m_pPanel->GetWidgetByName("ArrowDown"))
			pWidget->SetReleaseLMBEventDg(UI_DELEGATE(UISpriteSet, OnScrollDown));
		if (ui::UIWidget* pWidget = m_pPanel->GetWidgetByName("Exit"))
			pWidget->SetReleaseLMBEventDg(UI_DELEGATE(UISpriteSet, OnHide));

		for (int i=0; i<WIDGET_C; i++)
		{
			m_WidgetA[i] = m_pPanel->GetWidgetByNameEx("Entry%i", i+1);
		}
	}
	Show(m_RenderName);
}

UISpriteSet::~UISpriteSet()
{
	Hide();
	if (m_pPanel)
	{
		if (ui::UIWidget* pWidget = m_pPanel->GetWidgetByName("ArrowUp"))
			pWidget->SetReleaseLMBEventDg(0);
		if (ui::UIWidget* pWidget = m_pPanel->GetWidgetByName("ArrowDown"))
			pWidget->SetReleaseLMBEventDg(0);
		if (ui::UIWidget* pWidget = m_pPanel->GetWidgetByName("Exit"))
			pWidget->SetReleaseLMBEventDg(0);

		for (int i=0; i<WIDGET_C; i++)
		{
			if (m_WidgetA[i])
				m_WidgetA[i]->SetReleaseLMBEventDg(0);
		}
	}
}

void	UISpriteSet::Show(bool	RenderName)
{
	m_RenderName = RenderName;
	if (m_pPanel)
	{
		m_pPanel->SetIsVisible(true);
		ui::UIManager::Instance().PushPanelToFront(m_pPanel);
	}

}

void	UISpriteSet::Reset()
{
	m_Sprites.resize(0);
}

void	UISpriteSet::UpdateSprites()
{
	for (unsigned int i=0; i<WIDGET_C; i++)
	{
		if (!m_WidgetA[i]) continue;
		int	SpriteI = m_Offset + i;
		if (SpriteI < (int)m_Sprites.size())
		{
			m_WidgetA[i]->SetImage(ui::UIWidget::WI_MOUSE_OFF, m_Sprites[SpriteI]);
			m_WidgetA[i]->SetReleaseLMBEventDg(UI_DELEGATE(UISpriteSet, OnElementSelected));		
		} else
		{
			m_WidgetA[i]->SetImage(ui::UIWidget::WI_MOUSE_OFF, " ");
			m_WidgetA[i]->SetReleaseLMBEventDg(NULL);
		}
	}
}

void	UISpriteSet::BuildAll()
{
	Reset();
	for (unsigned int i=0; i<ui::SpriteSet::Instance().GetElementC(); i++)
	{
		m_Sprites.push_back(ui::SpriteSet::Instance().GetElementByIndex(i)->Name);
	}
	UpdateSprites();
}

void	UISpriteSet::BuildSprite(const std::string& SpriteFile, bool ShouldReset)
{
#ifdef _ENABLE_LUABIND

	if (ShouldReset)	Reset();
	// scan a specific lua file
	LuaState* pState = ScriptHelper::CreateLuaState();
	if (!ScriptHelper::DoFile(*pState, SpriteFile))
	{
		_LOG(MSG_ERROR, "Unable to load Script from " << SpriteFile << "!");
		LuaState::Destroy( pState );
	}  else
	{
		{
			LuaObject	ObjTable = pState->GetGlobal("Sprites");
			if (ObjTable.IsTable())
			{
				for (int i=0; i<ObjTable.GetTableCount(); i++)
				{
					LuaObject	Obj = ObjTable.GetByIndex(i+1);
					std::string Sprite = ScriptHelper::GetTableString(Obj, "Name"); 
				
					m_Sprites.push_back(Sprite);
				}
			}
		}
		LuaState::Destroy( pState );
	}
	UpdateSprites();
#endif
}


void	UISpriteSet::Tick(float dt)
{
	if (m_ToClose)
	{
		m_ToClose = false;
		Hide();
	}


}


void	UISpriteSet::BuildDir(const std::string& Directory, bool ShouldReset)
{
	if (ShouldReset) Reset();
	script::FileList		List;
	List.Build(Directory);
	for ( int i=0; i<List.GetFileC(); i++)
	{
		m_Sprites.push_back(List.GetFileName(i));
	}
	UpdateSprites();
}

void		UISpriteSet::Scroll(int Dir)
{
	if (Dir < 0)
	{
		m_Offset-=6;
	} else
	{
		m_Offset+=6;
	}

	UTIL_CLAMP(m_Offset, 0, UTIL_HIGH(0, (int)m_Sprites.size()-WIDGET_C));
	UpdateSprites();
}

void DELEGATE_CALL	UISpriteSet::OnScrollUp(ui::UIWidget::WIDGET_EVENT Event, ui::UIWidget* pWidget)
{
	Scroll(-1);
}
void DELEGATE_CALL	UISpriteSet::OnScrollDown(ui::UIWidget::WIDGET_EVENT Event, ui::UIWidget* pWidget)
{
	Scroll(1);
}

void DELEGATE_CALL	UISpriteSet::OnElementSelected(ui::UIWidget::WIDGET_EVENT Event, ui::UIWidget* pWidget)
{
	if (m_pBrush)
	{
		m_pBrush->UpdateSelection(pWidget->GetSprite(ui::UIWidget::WI_MOUSE_OFF)->GetFilename());
		m_ToClose = true;
	}
}
void DELEGATE_CALL	UISpriteSet::OnHide(ui::UIWidget::WIDGET_EVENT Event, ui::UIWidget* pWidget)
{
	Hide();
}
